# VirtualSelect 虚拟选择器

VinVirtualSelect 是基于 Element UI Select (opens new window) 组件的虚拟滚动增强版本,完全继承了 Element UI Select 的所有功能和 API,同时支持大数据量下的高性能渲染。

TIP

关于选择器的基础用法,请参考 Element UI Select 文档 (opens new window)。本文档主要介绍 VinVirtualSelect 的增强特性。

# 基础用法

基础的虚拟选择器用法。

性能提示

当前示例加载了 10000 条数据,但依然保持流畅的交互体验:

  1. 滚动列表观察是否流畅
  2. 输入关键字进行搜索
  3. 选中/取消选中选项

VinVirtualSelect 通过虚拟滚动技术,确保在大数据量下依然保持高性能。

通过 options 属性传入大量选项数据,组件会自动应用虚拟滚动优化。

TIP

VinVirtualSelect 可以轻松处理大量数据的渲染,而不会影响性能。

<template>
  <div class="select-demo">
    <div class="tip-section">
      <div class="tip-title">
        <i class="el-icon-info"></i>
        <span>性能提示</span>
      </div>
      <div class="tip-content">
        <p>当前示例加载了 10000 条数据,但依然保持流畅的交互体验:</p>
        <ol>
          <li>滚动列表观察是否流畅</li>
          <li>输入关键字进行搜索</li>
          <li>选中/取消选中选项</li>
        </ol>
        <p class="tip-highlight">VinVirtualSelect 通过虚拟滚动技术,确保在大数据量下依然保持高性能。</p>
      </div>
    </div>

    <div class="select-group">
      <vin-virtual-select
        v-model="value"
        :options="options"
        placeholder="请选择"
        filterable
        clearable
        :beautify-scroller-style="true"
      >
      </vin-virtual-select>
    </div>
  </div>
</template>

<script>
export default {
  name: 'BasicSelect',
  data() {
    return {
      value: '',
      options: Object.freeze(Array.from({ length: 50000 }, (_, index) => ({
        value: `value${index}`,
        label: `选项 ${index + 1}`
      })))
    };
  }
};
</script>

<style lang="scss" scoped>
.select-demo {
  padding: 20px;
}

.tip-section {
  margin-bottom: 30px;
  background-color: #f0f9eb;
  border-radius: 4px;
  padding: 16px 20px;
  border-left: 5px solid #67c23a;
}

.tip-title {
  color: #67c23a;
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
}

.tip-title i {
  margin-right: 8px;
  font-size: 18px;
}

.tip-content {
  color: #666;
  line-height: 1.6;
}

.tip-content ol {
  margin: 12px 0;
  padding-left: 20px;
}

.tip-content li {
  margin: 8px 0;
}

.tip-highlight {
  color: #67c23a;
  font-weight: 500;
  margin-top: 12px;
  font-size: 14px;
}

.select-group {
  margin-bottom: 30px;
  
  .vin-virtual-select {
    width: 300px;
  }
}
</style> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
显示代码

# 性能对比

Element UI Select 与 VinVirtualSelect 在大数据量下的性能对比。

性能对比演示 (50000条数据)

Element UI Select:
常规渲染可能导致性能问题
Vin Virtual Select:
虚拟滚动确保流畅体验

通过对比可以看到,在处理大量数据时 VinVirtualSelect 的性能优势。

<template>
  <div class="compare-demo">
    <div class="compare-section">
      <h4>
        <i class="el-icon-view"></i>
        性能对比演示 (50000条数据)
      </h4>
      <div class="compare-row">
        <div class="compare-item">
          <div class="compare-title">Element UI Select:</div>
          <el-select
            v-model="value1"
            placeholder="请选择"
            filterable
            clearable
          >
            <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
          <div class="compare-desc">常规渲染可能导致性能问题</div>
        </div>
        <div class="compare-item">
          <div class="compare-title">Vin Virtual Select:</div>
          <vin-virtual-select
            v-model="value2"
            :options="options"
            placeholder="请选择"
            filterable
            clearable
            :beautify-scroller-style="true"
          >
          </vin-virtual-select>
          <div class="compare-desc">虚拟滚动确保流畅体验</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CompareSelect',
  data() {
    return {
      value1: '',
      value2: '',
      options: Object.freeze(Array.from({ length: 50000 }, (_, index) => ({
        value: `value${index}`,
        label: `选项 ${index + 1}`
      })))
    };
  }
};
</script>

<style lang="scss" scoped>
.compare-demo {
  padding: 20px;
}

.compare-section {
  padding: 24px;
  background-color: #f5f7fa;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
}

.compare-section h4 {
  margin-top: 0;
  margin-bottom: 20px;
  color: #606266;
  display: flex;
  align-items: center;
}

.compare-section h4 i {
  margin-right: 8px;
  color: #409EFF;
}

.compare-row {
  display: flex;
  gap: 40px;
}

.compare-item {
  flex: 1;
  background-color: #fff;
  padding: 20px;
  border-radius: 4px;
  text-align: center;
}

.compare-title {
  font-weight: 500;
  color: #606266;
  margin-bottom: 16px;
}

.compare-desc {
  margin-top: 12px;
  color: #909399;
  font-size: 13px;
  line-height: 1.4;
}

.el-select,
.vin-virtual-select {
  width: 300px;
}
</style> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
显示代码

# API

# Props

参数 说明 类型 可选值 默认值
options 选项数据数组 array - []
value / v-model 绑定值 string / number / array - -
multiple 是否多选 boolean - false
disabled 是否禁用 boolean - false
valueKey 选项对象中值的键名 string - 'value'
labelKey 选项对象中标签的键名 string - 'label'
minItemSize 选项的最小高度 number - 34
beautifyScrollerStyle 是否美化滚动条样式 boolean - false
dropdownItemsCount 下拉框可见选项数量 number - 6

# Events

事件名称 说明 回调参数
change 选中值发生变化时触发 目前的选中值
visible-change 下拉框出现/隐藏时触发 出现则为 true,隐藏则为 false
remove-tag 多选模式下移除tag时触发 移除的tag值
clear 可清空的单选模式下用户点击清空按钮时触发 -
blur 当 input 失去焦点时触发 (event: Event)
focus 当 input 获得焦点时触发 (event: Event)

# Slots

插槽名 说明
label 选项的自定义内容,参数为 { item }